﻿using System.Runtime.CompilerServices;

namespace System {

    public interface IPoolObject : IObject {

        void Allocate();
    }

    public abstract class KHBD_PoolObject : IPoolObject, IDisposable {

        public event IObject.DisposingDelegate Disposing;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        protected void AssertDispose() {
            if (IsDisposed || IsDisposing) {
                UnityEngine.Debug.LogError($"正在使用已经回收的对象 ({nameof(IsDisposed)}={IsDisposed},{nameof(IsDisposing)}={IsDisposing},{nameof(Type)}={GetType().FullName})");
                throw new NullReferenceException();
            }
        }

        protected bool IsDisposing { get; private set; }

        public bool IsDisposed { get; private set; }

        private bool m_IsAllocated;

        protected abstract void Allocate();
        void IPoolObject.Allocate() => DoAllocate();
        private void DoAllocate() {
            if (m_IsAllocated) {
                return;
            }
            m_IsAllocated = true;
            IsDisposed = false;
            Allocate();
        }

        protected abstract void Release();
        void IDisposable.Dispose() => DoDispose();
        private void DoDispose() {
            if (!IsDisposed) {
                if (Disposing != null) {
                    Disposing.Invoke();
                    Disposing.Clear();
                    Disposing = null;
                }
                IsDisposing = true;
                Release();
                IsDisposed = true;
                IsDisposing = false;
                KHBD.TypeMap.Recycle(this);
                m_IsAllocated = false;
            }
        }
    }
}